/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fjala.softure.tree.sorted;

import java.util.ArrayList;
import java.util.List;
import org.fjala.softure.tree.AbstractNode;
import org.fjala.softure.tree.Node;

/**
 * Node implementation to keep a sorted tree.
 *
 * @author Dann Meneses
 *
 * @param <T> Type of data
 */
public class BinaryNode<T extends Comparable<T>> extends AbstractNode<T> {

    /**
     * Right child of the node.
     */
    protected BinaryNode<T> right;
    /**
     * Left child of the node.
     */
    protected BinaryNode<T> left;

    public BinaryNode(T data, Node<T> parent) {
        super(data, parent);
    }

    @Override
    public List<Node<T>> getChildren() {
        List<Node<T>> list = new ArrayList<Node<T>>();
        list.add(left);
        list.add(right);
        return list;
    }

    @Override
    public boolean hasChildren() {
        return right != null || left != null;
    }

    @Override
    public void addChild(Node<T> child) {
        if (this.data.compareTo(child.getData()) >= 0) {
            if (left == null) {
                left = (BinaryNode<T>) child;
            } else {
                child.setParent(left);
                left.addChild(child);
            }
        } else {
            if (right == null) {
                right = (BinaryNode<T>) child;
            } else {
                child.setParent(right);
                right.addChild(child);
            }
        }
    }

    @Override
    public int getChildCount() {
        return getChildren().size();
    }

    @Override
    public void removeChild(Node<T> child) {
        if (left.equals(child)) {
            left = null;
        }

        if (right.equals(child)) {
            right = null;
        }
    }

    /**
     * Replace a child with a new node. Old child of the old node will be lost.
     *
     * @param oldNode Node to replace
     * @param newNode Node to add
     */
    public void replaceChild(Node<T> oldNode, Node<T> newNode) {
        if (left != null && oldNode.getData().equals(left.data)) {
            left = (BinaryNode<T>) newNode;
        }
        if (right != null && oldNode.getData().equals(right.data)) {
            right = (BinaryNode<T>) newNode;
        }
    }

    @Override
    public String toString() {
        return data + "{l=" + left + ", r=" + right + '}';
    }
}
